#include "sprite_sheet.h"
#include "game_engine.h"
#include "utility.h"
#include <sstream>

SpriteSheet::SpriteSheet(std::string imageName, bool alphaFormat, int numFrames)
	: Sprite(imageName, alphaFormat) //Load by normal sprite contructor
{
	//std::stringstream logLine;
	//logLine << "SpriteSheet(): frames: " << numFrames;
	//log_info(logLine.str());

	frame = 0;
	frameOffset = 0;
	numberFrames = numFrames;
	animated = false;
	life = 0.0;
	OnAnimationCallback = NULL;
	AnimationCallbackObject = NULL;

	//Get correct frame width, excluding border
	SDL_Surface* img = GameEngine::getResources()->GetImage(resourceName, alphaFormat);
	if (img != NULL)
	{
		frameOffset = ((img->w - (SPRITE_SHEET_BORDER_WIDTH * (numFrames-1))) / numFrames);
	}
}

void SpriteSheet::setResource(std::string imageName, bool alphaFormat, int numFrames)
{
	frame = 0;
	frameOffset = 0;
	numberFrames = numFrames;
	life = 0.0;

	Sprite::setResource(imageName, alphaFormat); //Update resource name

	//Get correct frame width, excluding border
	SDL_Surface* img = GameEngine::getResources()->GetImage(resourceName, alphaFormat);
	if (img != NULL)
	{
		frameOffset = ((img->w - (SPRITE_SHEET_BORDER_WIDTH * (numFrames-1))) / numFrames);
	}
}

void SpriteSheet::Update(double timeDelta)
{
	if (animated)
	{
		life += timeDelta;
		double frameSpan = (animationSpan / numberFrames);
		if (life >= frameSpan)
		{
			while (life >= frameSpan)
				life -= frameSpan;
			AdvanceFrame();
			if (OnAnimationCallback != NULL)
			{
				(*OnAnimationCallback)(AnimationCallbackObject, this); //Call callback to handle changing frames
			}
			/*
			if (resourceName.find("_fighting") != std::string::npos && parent != NULL && frame == 1)
			{
				double x, y;
				this->parent->getPosition(x, y);
				x -= 2;
				this->parent->setPosition(x, y);
			}
			*/
		}
	}

	/*
	if (resourceName.find("_movement") != std::string::npos && parent != NULL)
	{
		double x, y;
		this->parent->getPosition(x, y);
		x += (Sint16)(timeDelta * 200);
		this->parent->setPosition(x, y);
	}
	*/

	//Update children
	RenderTarget::Update(timeDelta);
}

void SpriteSheet::AdvanceFrame()
{
	frame++;
	if (frame >= numberFrames)
		frame = 0;
}

void SpriteSheet::Render(SDL_Surface* screen)
{
	Sint16 dx, dy, sx, sy, sw, sh;

	SDL_Surface* img = NULL;
	//Get image to render with
	img = getRenderImage();
	if (img != NULL)
	{
		getScreenCoords(dx, dy);

		sx = 0 + frame * (frameOffset + SPRITE_SHEET_BORDER_WIDTH);
		sy = 0;
		sw = frameOffset;
		sh = img->h;

		apply_partial_surface(sx, sy, sw, sh, dx, dy, img, screen);
    
	}
	//Render children
    RenderTarget::Render(screen);
}


void SpriteSheet::setAnimationSpan(double span)
{
	animationSpan = span;
}
double SpriteSheet::getAnimationSpan()
{
	return animationSpan;
}

PD_vect2 SpriteSheet::getFrameSize()
{
	//Get the base sprite size, which gives us the correct height
	PD_vect2 size = getSize();
	//The width is the frame offset, calculated by original image size and number of frames in constructor
	size.x = frameOffset;
	return size;
}

void SpriteSheet::getScreenCoords(Sint16 &x, Sint16 &y)
{
	SDL_Surface* img = NULL;
	//Get image to render
	img = getRenderImage();
	RenderTarget::getScreenCoords(x, y);
	if (centered) {
		x = x - (frameOffset / 2);
		y = y - (img->h / 2);
	}
}